package com.itheima.controller;

import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * EmpController_控制层用于响应前端http请求,返回从xml中读取到的员工的数据
 * 但不是所有任务都在控制层完成,控制层只负责收请求参数,发响应数据,而具体的哪里来的数据,对数据进行什么样的操作,都不在控制层完成,而是由控制层调用服务层对象,在服务层对象中完成对数据的处理,而服务层对象自身的数据又来自于数据访问层对象,分三层各自完成任务,符合"单一职责原则"这就是spring的三层架构(controller控制层-service服务层-DAO(date access object)数据访问层).实际上就是3个包下面定义三个类,服务层与数据访问层中的类一般定义成接口和实现类的形式
 */

/*Spring三层架构(优点是:复用性强,便于维护,利于拓展)
controller:控制层，接收前端发送的请求，对请求进行处理，并响应数据。
service:业务逻辑层，处理具体的业务逻辑。
dao:数据访问层(Data Access Object)(持久层），负责数据访问操作，包括数据的增、删、改、查。
 */


@RestController  /*@RestController注解 = @Controller注解 + @ResponseBody注解
其中@Controller注解表示 *///TODO  ?

public class EmpController_控制层_IOC控制反转DI依赖注入 {
    /**
     * 控制反转： Inversion Of Control，简称IOC。对象的创建控制权由程序自身转移到外部（容器），这种思想称为控制反转。
     * 依赖注入： Dependency Injection，简称DI。容器为应用程序提供运行时，所依赖的资源，称之为依赖注入。
     * Bean对象：Spring IOC容器 中 由Spring创建、管理的对象，称之为bean对象。
     */


    @Autowired /*该注释表示,这个变量需要被Spring的IOC(inversion of control)容器自动装配,需要向Spring的IOC(控制反转)容器索要由Spring自动创建的实现类对象,这一由IOC容器给变量赋值的过程称之为"依赖注入"

    至于IOC容器中的对象从何而来,实际上就是在定义实现类的时候由程序员加注解,告诉Spring我需要你去创建这个类的对象然后赋值给我用注解标注的变量,将这一由Spring创建对象并自动赋值的控制权力转移过程,称之为"控制反转"(IOC,inversion of control)*/
    private EmpService empService;

    @RequestMapping("/listEmp")
    public Result listEmp() {
        try {
            List<Emp> empList = empService.listEmp();
            //将数据放入result中
            return Result.success(empList);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("对不起，数据读取失败！！");
        }
    }
}

/**
 * 👀DI(Dependency Injection)依赖注入详解
 *
 * @Autowired注解，默认是按照类型进行，如果存在多个相同类型的bean， 如:EmpService接口有两个实现类EmpServiceImpl_1和EmpServiceImpl_2两个实现类都使用了@Servie注解进行标注,而在Controller中@Autowired自动注入的是接口类型的EmpService empservice对象,那么将会报错,因为Spring不知道到底应该用哪个实现类的对象进行依赖注入
 * <p>
 * 通常有3种方式解决这一问题:
 * @Primary
 * @Qualifier
 * @Resource 1.使用@Primary将其中一个实现类指定为主要的服务层bean对象,如果有多个服务层实现类将会优先依赖注入主要的实现类对象
 * @Primary
 * @Service public class EmpServiceImpl1 implements EmpService {
 * }
 * <p>
 * 2.
 * <p>
 * (qualify v.使具有资格
 * qualifier n. 合格者,具有资格者
 * qualified a.有资格的,合格的
 * qualification n.资格资历)
 * <p>
 * 在控制层中自动注入服务层对象时使用@Qualifier("alias1")来指定要注入哪个实现类对象,即谁是'合格者',对应的服务层实现类上@Service时就应该给出各自的别名@Service("alias1")@Service("alias2")
 * @RestController public class EmpController {
 * @Autowired
 * @Qualifier("empServiceImpl1") private EmpService empService ;
 * ...
 * }
 * <p>
 * 3.一种过时的方式@Resource
 * @RestController public class EmpController {
 * @Resource(type=实现类.class 或者 接口.class,name = "empServiceImpl1")//实现类不止一个时需要加上type=实现类.class 或者 接口.class
 * //等价于
 * //@Autowired
 * //@Qualifier("empServiceImpl1")
 * <p>
 * private EmpService empService ;
 * <p>
 * -----------------------------------------------------------------------
 * <p>
 * 总结:
 * 1. 依赖注入的注解
 * @Autowired：默认按照类型自动装配。 如果同类型的bean存在多个：
 * @Primary
 * @Autowired + @Qualifier("bean的名称")
 * @Resource(name="bean的名称")多个bean时还需要加上type=实现类.class 或者 接口.class
 * <p>
 * 2. @Resource 与 @Autowired区别
 * @Autowired 是spring框架提供的注解，而@Resource是JDK提供的注解。
 * @Autowired 默认是按照类型注入，而@Resource默认是按照名称注入。
 * <p>
 * -----------------------------------------------------------------------
 */
